package com.dly.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dly.blog.domain.Role;
import com.dly.blog.domain.RoleMenu;
import com.dly.blog.domain.RolePermission;
import com.dly.blog.domain.ro.menu.UpdateRoleMenuRO;
import com.dly.blog.domain.ro.permission.UpdateRolePermissionRO;
import com.dly.blog.domain.ro.role.HomePageRO;
import com.dly.blog.mapper.RoleMapper;
import com.dly.blog.mapper.RoleMenuMapper;
import com.dly.blog.mapper.RolePermissionMapper;
import com.dly.blog.service.RoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dly.blog.utile.CollectionUtils;
import org.springframework.stereotype.Service;
import com.dly.blog.domain.vo.role.RoleVO;
import com.dly.blog.domain.ro.role.RolePageRO;
import com.dly.blog.domain.ro.role.RoleAddRO;
import com.dly.blog.domain.ro.role.RoleEditRO;
import com.dly.blog.domain.vo.PageVO;
import org.springframework.beans.BeanUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import lombok.AllArgsConstructor;
import cn.hutool.core.collection.ListUtil;

import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 角色 服务实现类
 * </p>
 *
 * @author DLY
 * @since 2024-11-11 10:59:37
 */
@Service
@AllArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    private final RoleMenuMapper roleMenuMapper;

    private final RolePermissionMapper rolePermissionMapper;


    @Override
    public PageVO<RoleVO> getRolePage(RolePageRO rolePageRO) {
        Page<Role> page = baseMapper.selectPage(rolePageRO.buildIPage(), new LambdaQueryWrapper<>());
        return PageVO.buildMyBatis(page, role -> {
            RoleVO roleVO = new RoleVO();
            BeanUtils.copyProperties(role, roleVO);
            return roleVO;
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRole(RoleAddRO roleAddRO) {
        Role role = new Role();
        BeanUtils.copyProperties(roleAddRO, role);
        baseMapper.insert(role);
    }

    @Override
    public RoleVO getRole(String id) {
        Role role = baseMapper.selectById(id);
        RoleVO roleVO = new RoleVO();
        BeanUtils.copyProperties(role, roleVO);
        return roleVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeRole(String[] ids) {
        baseMapper.deleteBatchIds(ListUtil.toList(ids));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editRole(RoleEditRO roleEditRO) {
        Role role = new Role();
        BeanUtils.copyProperties(roleEditRO, role);
        baseMapper.updateById(role);
    }

    @Override
    public List<RoleVO> getRoleAll() {
        return baseMapper.selectList(new LambdaQueryWrapper<>()).stream().map(role -> {
            RoleVO roleVO = new RoleVO();
            BeanUtils.copyProperties(role, roleVO);
            return roleVO;
        }).toList();
    }

    @Override
    public List<String> getRoleMenu(String roleId) {
        return baseMapper.searchAllMenuByRoleId(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoleMenu(UpdateRoleMenuRO updateRoleMenuRO) {

        List<String> remove = baseMapper.searchAllMenuByRoleId(updateRoleMenuRO.getRoleId());
        List<String> add = updateRoleMenuRO.getMenuIds();

        //处理
        CollectionUtils.getDifferenceResult(remove, add);

        //清除
        if(CollectionUtils.isNotEmpty(remove)) {
            roleMenuMapper.delete(new LambdaQueryWrapper<RoleMenu>()
                    .eq(RoleMenu::getRoleId, updateRoleMenuRO.getRoleId())
                    .in(RoleMenu::getMenuId, remove)
            );
        }

        //重新插入
        add.forEach(menuId -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(updateRoleMenuRO.getRoleId());
            roleMenu.setMenuId(menuId);
            roleMenuMapper.insert(roleMenu);
        });
    }

    @Override
    public List<String> getRolePermission(String roleId) {
        return rolePermissionMapper.selectList(
                        new LambdaQueryWrapper<RolePermission>()
                                .eq(RolePermission::getRoleId, roleId))
                .stream()
                .map(RolePermission::getPermissionId).toList();
    }

    @Override
    public void updateRolePermission(UpdateRolePermissionRO updateRolePermissionRO) {
        List<String> remove = baseMapper.searchAllPermissionByRoleId(updateRolePermissionRO.getRoleId());
        List<String> add = updateRolePermissionRO.getPermissionIds();

        //处理
        CollectionUtils.getDifferenceResult(remove, add);

        //清除
        if(CollectionUtils.isNotEmpty(remove)) {
            rolePermissionMapper.delete(new LambdaQueryWrapper<RolePermission>()
                    .eq(RolePermission::getRoleId, updateRolePermissionRO.getRoleId())
                    .in(RolePermission::getPermissionId, remove)
            );
        }

        //重新插入
        add.forEach(permissionId -> {
            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(updateRolePermissionRO.getRoleId());
            rolePermission.setPermissionId(permissionId);
            rolePermissionMapper.insert(rolePermission);
        });
    }

    @Override
    public String getHomePage(String roleId) {
        return Optional.ofNullable(baseMapper.searchHomePage(roleId)).orElse("home");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setHomePage(HomePageRO homePageRO) {
        roleMenuMapper.update(new LambdaUpdateWrapper<RoleMenu>()
                        .eq(RoleMenu::getRoleId, homePageRO.getRoleId())
                .set(RoleMenu::getIsHome, 0)
        );

        roleMenuMapper.update(new LambdaUpdateWrapper<RoleMenu>()
                .eq(RoleMenu::getRoleId, homePageRO.getRoleId())
                        .eq(RoleMenu::getMenuId, homePageRO.getMenuId())
                .set(RoleMenu::getIsHome, 1)
        );
    }
}
